package com.jwsoft.manager.core.integration.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.data.core.util.PagerUtil;
import com.bifang.module.base.common.vo.system.UserVO;
import com.bifang.module.system.core.dao.service.SysUserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.enums.DisposeStatusTypeEnum;
import com.jwsoft.manager.common.vo.eduStudentEnrollPre.EduStudentEnrollPreKeyVO;
import com.jwsoft.manager.core.dao.model.EduStudentEnrollPre;
import com.jwsoft.manager.core.dao.service.EduStudentEnrollPreService;
import com.jwsoft.manager.core.util.EduHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.convert.Convert;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.bifang.engine.assistant.core.exception.AppException;
import org.springframework.util.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.jwsoft.manager.common.vo.eduBusiEnrollOrder.EduBusiEnrollOrderVO;
import com.jwsoft.manager.common.vo.eduBusiEnrollOrder.EduBusiEnrollOrderKeyVO;
import com.jwsoft.manager.common.vo.eduBusiEnrollOrder.EduBusiEnrollOrderQueryVO;
import com.jwsoft.manager.core.integration.EduBusiEnrollOrderIntegration;
import com.jwsoft.manager.core.dao.service.EduBusiEnrollOrderService;
import com.jwsoft.manager.core.dao.model.EduBusiEnrollOrder;

/**
 * 报名派号业务管理业务实现类
 *
 * @author zhiyuan
 * @since 2023-07-21
 */
@ApiService(funcCode = "busiEnrollOrder", title = "报名派号业务管理")
@Slf4j
public class EduBusiEnrollOrderIntegrationImpl implements EduBusiEnrollOrderIntegration {
    @Autowired
    public EduBusiEnrollOrderService eduBusiEnrollOrderService;
    @Autowired
    private EduHelper eduHelper;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private EduStudentEnrollPreIntegrationImpl eduStudentEnrollPreIntegration;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private EduStudentEnrollPreService eduStudentEnrollPreService;

    @Override
    @OpApi(funcCode = "busiEnrollOrder0001", title = "报名派号业务管理分页查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduBusiEnrollOrderVO> getList(EduBusiEnrollOrderQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        String nowDate = null;
        if (ObjectUtils.isEmpty(vo.getOrderYmd())) {
            LocalDate localDate = LocalDate.now();
            nowDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } else {
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
            nowDate = fmt.format(vo.getOrderYmd());
        }

        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        QueryWrapper<EduBusiEnrollOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduBusiEnrollOrder::getYear, eduHelper.thisYear())
                .eq(EduBusiEnrollOrder::getOrderYmd, nowDate)
                .eq(StringUtils.isNotBlank(vo.getIdcard()), EduBusiEnrollOrder::getIdcard, vo.getIdcard())
                .eq(!ObjectUtils.isEmpty(vo.getOrderType()), EduBusiEnrollOrder::getOrderType, vo.getOrderType())
                .eq(!ObjectUtils.isEmpty(vo.getDisposeStatus()), EduBusiEnrollOrder::getDisposeStatus, vo.getDisposeStatus())
                .eq(!ObjectUtils.isEmpty(vo.getOrderNum()), EduBusiEnrollOrder::getOrderNum, vo.getOrderNum())
                .orderByAsc(EduBusiEnrollOrder::getOrderNum);
        List<EduBusiEnrollOrder> list = eduBusiEnrollOrderService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduBusiEnrollOrder> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduBusiEnrollOrderVO> resultList = Convert.toList(EduBusiEnrollOrderVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0002", title = "报名派号业务管理根据主键查询详情", funcType = FuncTypeEnum.query)
    public EduBusiEnrollOrderVO getById(EduBusiEnrollOrderKeyVO vo) {
        EduBusiEnrollOrder entity = eduBusiEnrollOrderService.getById(vo.getBusiEnrollOrderId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduBusiEnrollOrderVO result = Convert.convert(EduBusiEnrollOrderVO.class, entity);
        return result;
    }

    /**
     * 保存前统一校验
     */
    @Override
    @OpApi(funcCode = "busiEnrollOrder0003", title = "报名派号业务管理保存前校验", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduBusiEnrollOrderVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0004", title = "报名派号业务管理新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "busiEnrollOrder0004",
            operationName = "报名派号业务管理新增",
            dataType = "busiEnrollOrderId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduBusiEnrollOrderVO add(EduBusiEnrollOrderVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduBusiEnrollOrder entity = Convert.convert(EduBusiEnrollOrder.class, vo);
        eduBusiEnrollOrderService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setBusiEnrollOrderId(entity.getBusiEnrollOrderId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0005", title = "报名派号业务管理修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "busiEnrollOrder0005",
            operationName = "报名派号业务管理修改",
            dataType = "busiEnrollOrderId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduBusiEnrollOrderVO edit(EduBusiEnrollOrderVO vo) {
        if (ObjectUtils.isEmpty(vo.getDisposeStatus())) {
            throw new AppException("派号修改状态不能为空!");
        }
        if (ObjectUtils.isEmpty(vo.getBusiEnrollOrderId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduBusiEnrollOrder oldEntity = eduBusiEnrollOrderService.getById(vo.getBusiEnrollOrderId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduBusiEnrollOrder entity = Convert.convert(EduBusiEnrollOrder.class, vo);
        entity.setDisposeStatus(vo.getDisposeStatus());
        UpdateWrapper<EduBusiEnrollOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(EduBusiEnrollOrder::getBusiEnrollOrderId, vo.getBusiEnrollOrderId())
                .eq(EduBusiEnrollOrder::getOrderVersion, oldEntity.getOrderVersion())
                .set(EduBusiEnrollOrder::getDisposeStatus, vo.getDisposeStatus())
                .set(EduBusiEnrollOrder::getUpdateName, SessionUtil.getUserId())
                .set(EduBusiEnrollOrder::getOrderVersion, oldEntity.getOrderVersion() + 1)
                .set(EduBusiEnrollOrder::getUpdateTime, new Date());
        eduBusiEnrollOrderService.update(updateWrapper);
        return vo;
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0006", title = "报名派号业务管理根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "busiEnrollOrder0006",
            operationName = "报名派号业务管理删除",
            dataType = "busiEnrollOrderId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduBusiEnrollOrderKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getBusiEnrollOrderId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduBusiEnrollOrder entity = eduBusiEnrollOrderService.getById(vo.getBusiEnrollOrderId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduBusiEnrollOrderService.removeById(vo.getBusiEnrollOrderId());
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0007", title = "报名派号业务叫号", funcType = FuncTypeEnum.update,publicFlag = BoolEnum.TRUE)
    @SaveOplog(
            operationType = "busiEnrollOrder0007",
            operationName = "报名派号业务叫号",
            dataType = "busiEnrollOrderId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduBusiEnrollOrderVO callOrderNum(EduBusiEnrollOrderQueryVO vo) {
        LocalDate localDate = LocalDate.now();
        String nowDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        QueryWrapper<EduBusiEnrollOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduBusiEnrollOrder::getYear, eduHelper.thisYear())
                .eq(EduBusiEnrollOrder::getOrderYmd, nowDate)
                .eq(EduBusiEnrollOrder::getDisposeStatus, DisposeStatusTypeEnum.DCL.getType())
                .orderByAsc(EduBusiEnrollOrder::getOrderNum);
        PageHelper.startPage(1, 1);
        List<EduBusiEnrollOrder> list = eduBusiEnrollOrderService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        EduBusiEnrollOrder enrollOrder = list.get(0);
        UpdateWrapper<EduBusiEnrollOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(EduBusiEnrollOrder::getBusiEnrollOrderId, enrollOrder.getBusiEnrollOrderId())
                .eq(EduBusiEnrollOrder::getOrderNum, enrollOrder.getOrderNum())
                .eq(EduBusiEnrollOrder::getOrderVersion, enrollOrder.getOrderVersion())
                .set(EduBusiEnrollOrder::getDisposeStatus, DisposeStatusTypeEnum.JXZ.getType())
                .set(EduBusiEnrollOrder::getUpdateName, SessionUtil.getUserId())
                .set(EduBusiEnrollOrder::getUpdateTime, new Date())
                .set(EduBusiEnrollOrder::getOrderVersion, enrollOrder.getOrderVersion() + 1);
        boolean updateFlag = eduBusiEnrollOrderService.update(updateWrapper);
        if (updateFlag) {
            EduBusiEnrollOrder eduBusiEnrollOrder = eduBusiEnrollOrderService.getById(enrollOrder.getBusiEnrollOrderId());
            return Convert.convert(EduBusiEnrollOrderVO.class, eduBusiEnrollOrder);
        } else {
            throw new AppException("业务处理繁忙，请刷新后重试！");
        }
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0008", title = "家长APP请求派号", funcType = FuncTypeEnum.insert,publicFlag = BoolEnum.TRUE)
    @Transactional
    public String appDistributeOrderNum(EduBusiEnrollOrderQueryVO vo) {

        if (ObjectUtils.isEmpty(vo.getIdcard())) {
            throw new AppException("身份证不能为空！！");
        }
        if (ObjectUtils.isEmpty(vo.getFullName())) {
            throw new AppException("姓名不能为空！！");
        }
        Integer year = eduHelper.thisYear();
        LocalDate localDate = LocalDate.now();
        String nowDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //UserVO userDetail = sysUserService.getUserDetail(SessionUtil.getUserId());
        QueryWrapper<EduBusiEnrollOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(EduBusiEnrollOrder::getSubmitterIdcard, vo.getSubmitterIdcard())
                .eq(EduBusiEnrollOrder::getOrderYmd,localDate)
                .in(EduBusiEnrollOrder::getDisposeStatus, DisposeStatusTypeEnum.DCL.getType(), DisposeStatusTypeEnum.JXZ.getType());
        long count = eduBusiEnrollOrderService.count(queryWrapper);
        if (count > 0) {
            EduBusiEnrollOrder busiEnrollOrder = eduBusiEnrollOrderService.getOne(queryWrapper, false);
            throw new AppException(String.format("当天有未处理摇号，编号:%s", busiEnrollOrder.getOrderNum()));
        }
        //获取当天分布式锁
        RLock lock = redissonClient.getLock(EduCache.Edu_ENROLL_ORDER_LOCK + nowDate);
        try {
            boolean isGetLock = lock.tryLock(5, 10, TimeUnit.SECONDS);
            if (isGetLock) {
                Long maxOrderNum = eduBusiEnrollOrderService.getMaxOrderNumByDate(nowDate);
                if (maxOrderNum == null) {
                    maxOrderNum = Long.valueOf(nowDate.replace("-","")+"0");
                }
                Long newOrderNum = maxOrderNum+1;;
                EduBusiEnrollOrder enrollOrder = new EduBusiEnrollOrder();
                //设置业务表和结果表主键
                enrollOrder.setStudentEnrollPreId(vo.getStudentEnrollPreId());
                enrollOrder.setBusiEnrollPreId(vo.getBusiEnrollPreId());

                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    enrollOrder.setOrderYmd(sdf.parse(nowDate));
                } catch (ParseException e) {
                    log.error("日期转换错误：" + e.getMessage());
                    throw new RuntimeException(e);
                }
                enrollOrder.setYear(year);
                enrollOrder.setOrderNum(newOrderNum);
                enrollOrder.setFullName(vo.getFullName());
                enrollOrder.setIdcard(vo.getIdcard());
                enrollOrder.setOrderVersion(newOrderNum);
                enrollOrder.setOrderType(vo.getOrderType());
                enrollOrder.setOrderInfo(vo.getOrderInfo());
               // enrollOrder.setSubmitterId(userDetail.getIdcard());
                enrollOrder.setSubmitterName(vo.getSubmitterName());
                enrollOrder.setSubmitterIdcard(vo.getSubmitterIdcard());
                enrollOrder.setDisposeStatus(DisposeStatusTypeEnum.DCL.getType());
                enrollOrder.setCreateName(SessionUtil.getUserId());
                enrollOrder.setCreateTime(new Date());
                enrollOrder.setMaterials(vo.getMaterials());
           //     enrollOrder.setParentIdcard(userDetail.getIdcard());
                enrollOrder.setUpdateName(SessionUtil.getUserId());
                enrollOrder.setUpdateTime(new Date());
                eduBusiEnrollOrderService.save(enrollOrder);
                return enrollOrder.getOrderNum()+"";
            } else {
                log.error("获取锁失败，无法生成派号编号");
            }
        } catch (InterruptedException e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
        return null;
    }

    /**
     * @param vo
     * @return
     */
    @Override
    @OpApi(funcCode = "busiEnrollOrder0009", title = "根据派号类型得到详情信息", funcType = FuncTypeEnum.query)
    @SaveOplog(
            operationType = "busiEnrollOrder0009",
            operationName = "根据派号类型得到详情信息",
            dataType = "ohter",
            auType = AuTypeEnum.OTHER)
    public Object getDetailsByOrderType(EduBusiEnrollOrderQueryVO vo) {
        if (ObjectUtils.isEmpty(vo.getBusiEnrollOrderId())) {
            throw new AppException("派号主键不能为空！");
        }
        //得到派号信息
        EduBusiEnrollOrder enrollOrder = eduBusiEnrollOrderService.getById(vo.getBusiEnrollOrderId());
        if (ObjectUtils.isEmpty(enrollOrder)) {
            throw new AppException("数据有误，请刷新后重试！");
        }
        EduStudentEnrollPreKeyVO params = new EduStudentEnrollPreKeyVO();
        //类型为信息修改，待处理或者进行中才进行处理
        if (enrollOrder.getOrderType().equals("0") &&
                (enrollOrder.getDisposeStatus().equals(DisposeStatusTypeEnum.DCL) || enrollOrder.getDisposeStatus().equals(DisposeStatusTypeEnum.JXZ))){
            if (enrollOrder.getStudentEnrollPreId() != null){
                //得到学生与采集信息
                EduStudentEnrollPre studentEnrollPre = eduStudentEnrollPreService.getById(enrollOrder.getStudentEnrollPreId());
                //判断与采集是否为空
                if (ObjectUtils.isEmpty(studentEnrollPre)){
                    params.setStudentEnrollPreId(enrollOrder.getStudentEnrollPreId());
                }
            }
            params.setBusiEnrollPreId(enrollOrder.getBusiEnrollPreId());
        }else {
            if (enrollOrder.getBusiEnrollPreId() != null){
                params.setBusiEnrollPreId(enrollOrder.getBusiEnrollPreId());
            }
            if (enrollOrder.getStudentEnrollPreId() != null){
                params.setStudentEnrollPreId(enrollOrder.getStudentEnrollPreId());
            }
        }

        return eduStudentEnrollPreIntegration.getById(params);
    }

    @Override
    @OpApi(funcCode = "busiEnrollOrder0010", title = "报名派号业务管理根据身份证查询详情", funcType = FuncTypeEnum.query,publicFlag = BoolEnum.TRUE)
    public EduBusiEnrollOrderVO appGetById(EduBusiEnrollOrderQueryVO vo) {
        if(StringUtils.isBlank(vo.getSubmitterIdcard())){
            throw new AppException("提交人身份证不能为空");
        }
        EduBusiEnrollOrderVO orderVO = new EduBusiEnrollOrderVO();
        QueryWrapper<EduBusiEnrollOrder> queryWrapper = new QueryWrapper<>();
//        List statusList = new ArrayList();
//        statusList.add("0");
//        statusList.add("1");
        LocalDate localDate = LocalDate.now();
        String nowDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        queryWrapper.lambda()
                .eq(EduBusiEnrollOrder::getSubmitterIdcard,vo.getSubmitterIdcard())
                .eq(EduBusiEnrollOrder::getOrderYmd,localDate)
                .orderByDesc(EduBusiEnrollOrder::getOrderNum);
        List<EduBusiEnrollOrder> list = eduBusiEnrollOrderService.list(queryWrapper);
        if(!CollectionUtils.isEmpty(list)){
            orderVO = Convert.convert(EduBusiEnrollOrderVO.class,list.get(0));
        }
        return orderVO;

    }
}

